/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-13
 * V4.0
 */
package com.jphenix.webserver.instancea;

import com.jphenix.standard.docs.ClassInfo;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;

import java.io.IOException;
import java.io.OutputStream;

/**
 * 服务输出流类
 * 
 * 2019-09-17 整理了代码格式
 * 2021-03-17 适配tomcat9中的 servlet-api.jar
 * 
 * @author 刘虻
 * 2006-9-15上午12:07:15
 */
@ClassInfo({"2021-03-17 20:56","服务输出流类"})
public class ServeOutputStream extends ServletOutputStream {

	private static final boolean STREAM_DEBUG = false;
	
	private boolean chunked;
	private boolean closed;
	private boolean inInclude;
	
	private ServeConnection conn;
	private OutputStream    out      = null; //输出流 
	private String          encoding = "ISO-8859-1"; //流编码   浏览器接收通常都用ISO-8859-1
	
	/**
	 * 构造函数
	 * 2007-9-30下午05:25:43
	 */
	public ServeOutputStream(OutputStream out, ServeConnection conn) {
		super();
		this.out = out;
		this.conn = conn;
	}

	/**
	 * 刷新
	 * @author 刘虻
	 * 2007-9-30下午05:26:26
	 */
	protected void refresh() {
		chunked = false;
		closed = false;
		inInclude = false;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午03:24:56
	 * @param set 母鸡
	 */
	protected void setChunked(boolean set) {
		chunked = set;
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午03:25:03
	 */
	@Override
    public void print(String s) throws IOException {
		write(s.getBytes(encoding));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午03:25:07
	 */
	@Override
    public void write(int b) throws IOException {
		write(new byte[] { (byte) b }, 0, 1);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午03:25:10
	 */
	@Override
    public void write(byte[] b) throws IOException {
		if(b==null) {
			return;
		}
		write(b, 0, b.length);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午03:25:14
	 */
	@Override
    public void write(byte[] b, int off, int len) throws IOException {
		if (closed) {
			throw new IOException("An attempt of writing to closed out.");
		}
		if (len == 0) {
			return;
		}
		conn.writeHeaders();
		if (chunked) {
			out.write((Integer.toHexString(len) + "\r\n").getBytes()); // encoding
			out.write(b, off, len);
			out.write("\r\n".getBytes());
		} else {
			try {
				out.write(b, off, len);
			}catch(Exception e) {
				throw e; //不一定是关闭了，还有可能是socket write error或者别的原因
				//throw new IOException("socket has closed");
			}
		}
		if (STREAM_DEBUG) {
			if (chunked) {
				System.err.println(Integer.toHexString(len));
			}
			System.err.print(new String(b, off, len));
			if (chunked) {
				System.err.println();
			}
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2007-9-30下午05:30:29
	 */
	@Override
    public void flush() throws IOException {
		if (closed) {
			return;
		}
		if (inInclude == false) {
			conn.writeHeaders();
		}
		out.flush();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2007-9-30下午05:31:23
	 */
	@Override
    public void close() throws IOException {
		if (closed) {
			return;
		}
		flush();
		if (inInclude == false) {
			if (chunked) {
				out.write("0\r\n\r\n".getBytes());
				if (STREAM_DEBUG) {
                    System.err.print("0\r\n\r\n");
                }
				out.flush();
			}
			if (conn.keepAlive == false) {
				out.close();
			}
		}
		closed = true;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午03:25:27
	 * @return 母鸡
	 */
	protected boolean isInInclude() {
		return inInclude;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午03:25:32
	 * @param _set 母鸡
	 */
	protected void setInInclude(boolean _set) {
		inInclude = _set;
	}

  @Override
  public boolean isReady() {
    return true;
  }

  @Override
  public void setWriteListener(WriteListener arg0) {}
}